package top.choviwu.garbage.sort.aop;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.util.Assert;
import top.choviwu.garbage.sort.annotation.GLog;
import top.choviwu.garbage.sort.entity.Garbage;
import top.choviwu.garbage.sort.entity.GarbageTimes;
import top.choviwu.garbage.sort.entity.Log;
import top.choviwu.garbage.sort.mapper.GarbageMapper;
import top.choviwu.garbage.sort.mapper.GarbageTimesMapper;
import top.choviwu.garbage.sort.mapper.LogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.choviwu.garbage.sort.redis.RedisRepository;
import top.choviwu.garbage.sort.util.CusAccessObjectUtil;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;

@Aspect
@Component
@Slf4j
public class LogAspect {


    @Autowired
    private HttpServletRequest request;
    @Autowired
    private LogMapper logMapper;
    @Autowired
    private GarbageMapper garbageMapper;
    @Autowired
    private GarbageTimesMapper garbageTimesMapper;
    @Autowired
    private RedisRepository redisRepository;


    @Pointcut(value = "@annotation(top.choviwu.garbage.sort.annotation.GLog)")
    public void point(){}

    @Around(value = "point()&&@annotation(log)")
    public Object around(ProceedingJoinPoint joinPoint, GLog log) throws Throwable {

        Object ret = joinPoint.proceed();


        return ret;
    }

    @AfterReturning(value ="point()&&@annotation(log)",returning = "val")
    public void returning(Object val, GLog log){

       insert(val,log);
    }
    @AfterThrowing(pointcut = "point()&&@annotation(log)",throwing = "throwable")
    public void afterThrow(Throwable throwable, GLog log){
        insert(throwable.getMessage(), log);
    }

    private void insert(Object val,GLog glog){
        String garbageName = request.getParameter("garbageName");
          garbageName = garbageName==null?request.getParameter("name"):garbageName;

        String openId = request.getParameter("openId");
        String host = request.getHeader("Host");
        String referer = request.getHeader("Referer");
        String agent = request.getHeader("User-Agent");
        log.info("Host >>>>> {} "  + "  Referer >>>>>{} ,  OpenId >>>>> {}  , " +
                "garbageName>>>>>>>{}" ,host,referer,openId,garbageName );
        log.info("User-Agent>>>>> {}",agent );
        Log log1 = new Log();
        log1.setContent(garbageName);
        log1.setResponse(val.toString());
        log1.setLogType(glog.value().ordinal());
        log1.setOpenId(openId);
        log1.setIp(CusAccessObjectUtil.getIpAddress(request));
        log1.setAddtime(LocalDateTime.now());
        log1.setAgent(agent);
        log1.setHost(host);
        log1.setReferer(referer);
        logMapper.insert(log1);
        System.out.println(val);
        Garbage garbage = garbageMapper.selectOne(new QueryWrapper<Garbage>().eq("g_name", garbageName));
        Optional.ofNullable(garbage).ifPresent(this::insertOrUpdateTimes);
    }

    private void insertOrUpdateTimes(Garbage garbage){
       GarbageTimes times = garbageTimesMapper.selectOne(Wrappers.query(new GarbageTimes()).eq("garbage_id",garbage.getId()));
       if(Objects.isNull(times)){
           times = new GarbageTimes();
           times.setTimes(1);
           times.setGarbageId(garbage.getId());
           Assert.isTrue(garbageTimesMapper.insert(times)>0,"insert_error");
       }else{
           times.setTimes(times.getTimes()+1);
           Assert.isTrue(garbageTimesMapper.updateById(times)>0,"update_error");
       }
    }
}
